package com.wwu.system.common.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wwu.common.constant.SecurityConst;
import com.wwu.common.utils.SpringUtils;
import com.wwu.common.web.ResultObj;
import com.wwu.system.entity.LoginLog;
import com.wwu.system.service.ILoginLogService;
import com.wwu.system.entity.SysUser;
import com.wwu.system.service.ISysUserService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.util.HashMap;

/**
 * 登陆成功处理器
 * @author 一蓑烟雨
 * @version 1.0.0
 * @date 2023-06-01 19:04
 */
@Component
public class SecurityLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    @Resource
    private ILoginLogService loginLogService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private SessionRegistry sessionRegistry;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //记录登陆成功日志
        if(!ObjectUtils.isEmpty(authentication)){
            asyncLoginLogSuccessHandler(request, response, authentication);
        }

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        PrintWriter out = response.getWriter();
        ResultObj bean = ResultObj.success(SecurityConst.LOGIN_SUCCESS);
        bean.setCode(HttpServletResponse.SC_OK);
        out.write(new ObjectMapper().writeValueAsString(bean));
        out.flush();
        out.close();
    }

    /**
     * 组织异步记录登陆日志实体
     * @param request
     * @param response
     * @param authentication
     * @author 一蓑烟雨
     * @date 2023/7/29 16:29
     */
    private void asyncLoginLogSuccessHandler(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
        LoginLog loginLog = new LoginLog();
        SysUser sysUser = (SysUser) authentication.getPrincipal();
        sysUser.setSessionId(request.getSession().getId());
        sysUser.setLoginIp(SpringUtils.getIpAddress(request));
        sysUser.setLoginTime(LocalDateTime.now());

        HashMap<String, String> hashMap = SpringUtils.getBrowserAndOsInfo(request);
        sysUser.setBrowser(hashMap.get("browserName"));
        sysUser.setOs(hashMap.get("osName"));

        //更新用户登录信息
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                sysUser, null, sysUser.getAuthorities());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        loginLog.setUserName(sysUser.getUsername());
        loginLog.setSessionId(sysUser.getSessionId());
        loginLog.setUserName(sysUser.getUsername());
        loginLog.setNickName(sysUser.getNickName());
        loginLog.setLoginIp(sysUser.getLoginIp());
        loginLog.setLoginRemoteHost(SpringUtils.getRemoteHost(request));
        loginLog.setLoginStatus(0);
        loginLog.setLoginDesc("登陆成功");
        loginLog.setBrowser(sysUser.getBrowser());
        loginLog.setOs(sysUser.getOs());
        loginLog.setLoginTime(sysUser.getLoginTime());

        //更新用户登陆时间
        sysUserService.updateUser(sysUser);
        //异步记录登陆日志
        loginLogService.saveLoginLog(loginLog);
    }
}